package api

import (
	"fmt"
	"holidayOpenAPI/infrustructure/domain"
	"holidayOpenAPI/repository"
	"log"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
)

// Response 统一返回结果
type Response struct {
	Code int         `json:"code"`
	Data interface{} `json:"data"`
	Msg  string      `json:"msg"`
}

func (response *Response) response(code int, data interface{}, msg string) {
	response.Code = code
	response.Data = data
	response.Msg = msg
}

//Routes api的统一入口
func Routes(r *gin.Engine) {
	r.GET("/holiday/holiDate/id/:id", getHolidayByID)
	r.GET("/holiday/holiDate/year/:year", getHolidayByYear)
	r.GET("/holiday/holiDate/dateStr/:dateStr", getHolidayByDateStr)
	r.GET("/holiday/holiDate/pageAndSize", getHolidayArrByPage)
	r.GET("/holiday/holiDate/totalSize", countHolidayByDuringTime)
	r.GET("/holiday/holiDate/period/:startTime/:endTime", getHolidayByPeriod)
	r.POST("/holiday/holiDate", createHoliday)
	r.PUT("/holiday/holiDate", updateHoliday)
	r.DELETE("/holiday/holiDate/id/:id", deleteHoloday)

	//静态页面，待优化
	r.GET("/holiday/index.html", indexPage)
	r.GET("/holiday/login.html", loginPage)
}

func getHolidayByID(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	response := Response{}
	if err == nil {
		holiday := repository.FindHoliByID(id)
		response.response(http.StatusOK, holiday, "")
		c.JSON(http.StatusOK, response)
	} else {
		response.response(http.StatusBadRequest, nil, "ID must is a number")
		c.JSON(http.StatusBadRequest, response)
	}

}

func getHolidayByDateStr(c *gin.Context) {
	holidayTime, err := time.Parse("2006-01-02", c.Param("dateStr"))
	response := Response{}
	if err == nil {
		holiday := repository.FindHoliByDate(holidayTime)
		response.response(http.StatusOK, holiday, "")
		c.JSON(http.StatusOK, response)
	} else {
		response.response(http.StatusBadRequest, nil, "dateString layout is yyyy-mm-dd")
		c.JSON(http.StatusBadRequest, response)
	}
}

func getHolidayArrByPage(c *gin.Context) {
	page, err := strconv.Atoi(c.DefaultQuery("page", "1"))
	size, err2 := strconv.Atoi(c.DefaultQuery("size", "10"))
	response := Response{}
	if err != nil || err2 != nil {
		response.response(http.StatusBadRequest, nil, "incorrected page or size")
		log.Println(err)
		log.Println(err2)
		c.JSON(http.StatusBadRequest, response)
	}
	holidayArr := repository.FindHoliByPage(page, size)
	response.response(http.StatusOK, holidayArr, "")
	c.JSON(http.StatusOK, response)
}

func getHolidayByPeriod(c *gin.Context) {
	startTime, err := time.Parse("2006-01-02", c.Param("startTime"))
	endTime, err2 := time.Parse("2006-01-02", c.Param("endTime"))
	response := Response{}
	if err != nil || err2 != nil {
		response.response(http.StatusBadRequest, nil, "incorrected startTime or endTime")
		log.Println(err)
		log.Println(err2)
		c.JSON(http.StatusBadRequest, response)
	}
	holidayArr := repository.FindHoliBetweenTime(startTime, endTime)
	response.response(http.StatusOK, holidayArr, "")
	c.JSON(http.StatusOK, response)

}

func countHolidayByDuringTime(c *gin.Context) {
	startTime, err := time.Parse("2006-01-02", c.DefaultQuery("startTime", "1970-01-01"))
	endTime, err2 := time.Parse("2006-01-02", c.DefaultQuery("endTime", "9999-12-31"))
	response := Response{}
	if err != nil || err2 != nil {
		response.response(http.StatusBadRequest, nil, "incorrected page or size")
		log.Println(err)
		log.Println(err2)
		c.JSON(http.StatusBadRequest, response)
	}
	count := repository.CountHoliDay(startTime, endTime)
	response.response(http.StatusOK, count, "")
	c.JSON(http.StatusOK, response)
}

func createHoliday(c *gin.Context) {
	holiDateDO := domain.HoliDateCreateDO{}
	response := Response{}
	if err := c.ShouldBind(&holiDateDO); err == nil {
		result := repository.CreateHoliday(holiDateDO)
		if result {
			response.response(http.StatusOK, "", "successed")
			c.JSON(http.StatusOK, response)
		} else {
			response.response(http.StatusBadRequest, nil, "failed inserting into holiday table")
			c.JSON(http.StatusBadRequest, response)
		}
	} else {
		response.response(http.StatusBadRequest, nil, err.Error())
		c.JSON(http.StatusBadRequest, response)
	}

}
func updateHoliday(c *gin.Context) {
	holiDateDO := domain.HoliDateUpdateDO{}
	response := Response{}
	if err := c.ShouldBind(&holiDateDO); err == nil {
		result := repository.UpdateHoliday(holiDateDO)
		if result {
			response.response(http.StatusOK, "", "successed")
			c.JSON(http.StatusOK, response)
		} else {
			response.response(http.StatusBadRequest, nil, "failed updating holiday")
			c.JSON(http.StatusBadRequest, response)
		}
	} else {
		response.response(http.StatusBadRequest, nil, err.Error())
		c.JSON(http.StatusBadRequest, response)
	}

}

func deleteHoloday(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	response := Response{}
	if err == nil {
		repository.DeleteHoliday(id)
		response.response(http.StatusOK, nil, "successed")
		c.JSON(http.StatusOK, response)
	} else {
		response.response(http.StatusBadRequest, nil, "ID must is a number")
		c.JSON(http.StatusBadRequest, response)
	}
}

func getHolidayByYear(c *gin.Context) {
	fmt.Println("year")
}

func indexPage(c *gin.Context) {
	c.HTML(http.StatusOK, "index.html", gin.H{})
}
func loginPage(c *gin.Context) {
	c.HTML(http.StatusOK, "login.html", gin.H{})
}
